﻿using System;
using System.Text;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using Quantum.Core;

namespace Quantum.RabbitMq
{
    public class Replier : RabbitMqConnetion, IReplyBehavior
    {
        private readonly Func<string, string> _messageHandler;

        public Replier(Func<string, string> messageHandler)
        {
            _messageHandler = messageHandler;
        }
        
        public void Send(string incomingMessagae)
        {
            using (var channel = Connection.CreateModel())
            {
                channel.QueueDeclare(queue: "rpc_queue", durable: false, exclusive: false, autoDelete: false, arguments: null);
                channel.BasicQos(0, 1, false);
                var consumer = new EventingBasicConsumer(channel);
                channel.BasicConsume(queue: "rpc_queue", autoAck: false, consumer: consumer);
                Console.WriteLine(" [x] Awaiting RPC requests");

                consumer.Received += (model, ea) =>
                {
                    string response = null;

                    var body = ea.Body;
                    var props = ea.BasicProperties;
                    var replyProps = channel.CreateBasicProperties();
                    replyProps.CorrelationId = props.CorrelationId;

                    try
                    {
                        var message = Encoding.UTF8.GetString(body);
                        Console.WriteLine("RabbitMqReplyer Got message:", message);
                        if (_messageHandler != null)
                        {
                            response = _messageHandler(message);
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(" [.] " + e.Message);
                        response = "";
                    }
                    finally
                    {
                        var responseBytes = Encoding.UTF8.GetBytes(response);
                        channel.BasicPublish(exchange: "", routingKey: props.ReplyTo, basicProperties: replyProps,
                            body: responseBytes);
                        channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);
                    }
                };
            }
        }

        public void SendObjects<TIn>(Outgoing<TIn> incomingMessage)
        {
        }
    }
}
